using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using Baik.Interface.Execution;
using Baik.Interface.Framework;

namespace Baik.Execution
{
    public class Object : Scope,  IObject
    {
        
        public Object(IInjector inject) : base(inject)
        {
            Dictionary.Add("isUndefined",  BuiltInFactory.Function(inject , (objects) => inject.Instantiate<IFalse>())); 
            Dictionary.Add("equals",  BuiltInFactory.Function(inject, BuiltinEquals));
            Dictionary.Add("toString",  BuiltInFactory.Function(inject, ToIString));
            Dictionary.Add("inherit",  BuiltInFactory.Function(inject, Inherit));
         }

        private IObject Inherit(IEnumerable<IObject> arg)
        {
            foreach(var p in arg)_parents.Add(p);
            return this;
        }

        private IObject ToIString(IEnumerable<IObject> arg)
        {
            var sw = new StringWriter();
            var rtn = Inject.Instantiate<IString>();
            rtn.Value = AsString();
            return rtn;
        }

        private IObject BuiltinEquals(IEnumerable<IObject> arg)
        {
            foreach (var obj in arg)
            {
                if (!((object) obj).Equals((object) this))
                {
                    return Inject.Instantiate<IFalse>();
                }
         
            }
            return Inject.Instantiate<ITrue>();
        }


        public virtual IObject Get(string name)
        {
            if (name == "this")
            {
                return this;
            }
            else
            {
                var rtn =  base.Get(name);
                if (rtn is IFunction)
                {
                    ((IFunction) rtn).HostingScope = this;
                }
                return rtn;
            }
        }

        public string Name { get; set; }
        private int _assigned = 0;
        public void Assign()
        {
            _assigned ++;
        }

        public void DeAssign()
        {
            _assigned --;
            if (_assigned < 1)
            {
                Destroy();
            }
        }

        


        public void Destroy()
        {
            //code goes here to remove object from memory;
        }
        private string VariablesStrings()
        {
            var sw = new StringWriter();
            Dictionary.Where(kvp => !(kvp.Value is BuiltInFunction)).Select(kvp => kvp.Key + " : " + kvp.Value.AsString() + ",").ToList().ForEach(sw.WriteLine);
            return sw.ToString();
        }
        public override string AsString()
        {
            {
                return "{" + VariablesStrings() +  "}";
            }
        }

      
    }
}